package cn.chiship.sdk.framework.util;

import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.base.constants.BaseConstants;
import cn.chiship.sdk.core.enums.BaseResultEnum;
import cn.chiship.sdk.core.exception.custom.BusinessException;
import cn.chiship.sdk.core.util.CsvUtils;
import cn.chiship.sdk.core.util.ObjectUtil;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.core.util.excel.ExcelFactory;
import cn.chiship.sdk.core.util.excel.core.ExcelEnum;
import cn.chiship.sdk.core.util.excel.core.ExcelService;
import cn.chiship.sdk.core.util.http.ResponseUtil;
import cn.chiship.sdk.framework.pojo.dto.export.ExportTransferDataDto;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 导出工具
 *
 * @author lijian
 */
public class ExportUtil {

    private static ExportUtil exportUtil;

    private ExportUtil() {
    }

    public static synchronized ExportUtil getInstance() {
        if (exportUtil == null) {
            exportUtil = new ExportUtil();
        }
        return exportUtil;
    }

    public byte[] getExportBytesByType(ExportTransferDataDto exportTransferDataDto) {
        String exportType = exportTransferDataDto.getExportType();
        if (StringUtil.isNullOrEmpty(exportType)) {
            throw new BusinessException("缺少参数【exportType】");
        }
        String sheetName = exportTransferDataDto.getSheetName();
        if (StringUtil.isNullOrEmpty(sheetName)) {
            throw new BusinessException("缺少参数【sheetName】");
        }
        String sheetTitle = exportTransferDataDto.getSheetTitle();
        if (StringUtil.isNullOrEmpty(sheetTitle)) {
            throw new BusinessException("缺少参数【sheetTitle】");
        }
        List<String> labels = exportTransferDataDto.getLabels();
        if (ObjectUtil.isEmpty(labels)) {
            throw new BusinessException("缺少参数【labels】");
        }
        List<List<String>> valueList = exportTransferDataDto.getValues();
        if (ObjectUtil.isEmpty(valueList)) {
            throw new BusinessException("暂无符合条件的数据，无法导出");
        }
        byte[] bytes;
        if (labels.size() != valueList.get(0).size()) {
            return new byte[0];
        }
        labels.add(0, "序号");
        AtomicInteger index = new AtomicInteger(1);
        valueList.forEach(item -> item.add(0, String.valueOf(index.getAndIncrement())));
        switch (exportType) {
            case BaseConstants.EXPORT_FORMAT_XLS:
                bytes = ExcelFactory.getExcelService(ExcelEnum.XLS).getWriteExcelBytes(sheetName, sheetTitle, labels,
                        valueList);
                break;
            case BaseConstants.EXPORT_FORMAT_XLSX:
                bytes = ExcelFactory.getExcelService(ExcelEnum.XLSX).getWriteExcelBytes(sheetName, sheetTitle, labels,
                        valueList);
                break;
            case BaseConstants.EXPORT_FORMAT_CSV:
                bytes = CsvUtils.getWriteCsvBytes(labels, valueList);
                break;
            case BaseConstants.EXPORT_FORMAT_JSON:
                bytes = analysisJSON(labels, valueList).toString().getBytes(StandardCharsets.UTF_8);
                break;
            case BaseConstants.EXPORT_FORMAT_TXT:
                StringBuilder write = new StringBuilder();
                String doubleTab = "        ";
                String enter = "\r\n";
                for (String lab : labels) {
                    write.append(lab).append(doubleTab);
                }
                write.append(enter);
                for (List<String> list : valueList) {
                    for (String val : list) {
                        write.append(val).append(doubleTab);
                    }
                    write.append(enter);
                }
                bytes = write.toString().getBytes(StandardCharsets.UTF_8);
                break;
            default:
                throw new BusinessException("不识别的导出格式：" + exportType);
        }
        return bytes;
    }

    /**
     * 通过字节
     *
     * @param response
     * @param exportTransferDataDto
     * @throws Exception
     */
    public void exportByBytes(HttpServletResponse response, ExportTransferDataDto exportTransferDataDto)
            throws Exception {
        String exportType = exportTransferDataDto.getExportType();
        if (StringUtil.isNullOrEmpty(exportType)) {
            throw new BusinessException("缺少参数【exportType】");
        }
        String fileName = exportTransferDataDto.getFileName();
        if (StringUtil.isNullOrEmpty(fileName)) {
            throw new BusinessException("缺少参数【fileName】");
        }
        byte[] bytes = exportTransferDataDto.getBytes();
        if (ObjectUtil.isEmpty(bytes)) {
            throw new BusinessException("缺少参数【bytes】");
        }
        switch (exportType) {
            case BaseConstants.EXPORT_FORMAT_XLS:
                ResponseUtil.xls(fileName, bytes, response);
                break;
            case BaseConstants.EXPORT_FORMAT_XLSX:
                ResponseUtil.xlsx(fileName, bytes, response);
                break;
            case BaseConstants.EXPORT_FORMAT_CSV:
                ResponseUtil.csv(fileName, bytes, response);
                break;
            case BaseConstants.EXPORT_FORMAT_JSON:
                ResponseUtil.json(fileName, bytes, response);
                break;
            case BaseConstants.EXPORT_FORMAT_TXT:
                ResponseUtil.text(fileName, bytes, response);
                break;
            default:
                throw new BusinessException("不识别的输出格式：" + exportType);
        }
    }

    /**
     * 通过指定数据导出
     */
    public void exportByType(HttpServletResponse response, ExportTransferDataDto exportTransferDataDto)
            throws Exception {
        String exportType = exportTransferDataDto.getExportType();
        String fileName = exportTransferDataDto.getFileName();
        String sheetName = exportTransferDataDto.getSheetName();
        String sheetTitle = exportTransferDataDto.getSheetTitle();
        List<String> labels = exportTransferDataDto.getLabels();
        List<List<String>> valueList = exportTransferDataDto.getValues();
        if (valueList.isEmpty()) {
            ResponseUtil.writeJson(response, BaseResult.error(BaseResultEnum.FAILED, "没有找到符合条件的记录!"));
            return;
        }
        if (labels.size() != valueList.get(0).size()) {
            ResponseUtil.writeJson(response, BaseResult.error(BaseResultEnum.FAILED, "标题列数与数值列数不匹配!"));
            return;
        }
        labels.add(0, "序号");
        AtomicInteger index = new AtomicInteger(1);
        valueList.forEach(item -> item.add(0, String.valueOf(index.getAndIncrement())));

        switch (exportType) {
            /**
             * 导出Excel
             */
            case BaseConstants.EXPORT_FORMAT_XLS:
            case BaseConstants.EXPORT_FORMAT_XLSX:
                exportExcel(fileName, sheetName, sheetTitle, labels, valueList, response, exportType);
                break;
            /**
             * 导出CSV
             */
            case BaseConstants.EXPORT_FORMAT_CSV:
                exportCsv(fileName, labels, valueList, response);
                break;
            /**
             * 导出JSON
             */
            case BaseConstants.EXPORT_FORMAT_JSON:
                exportJson(fileName, analysisJSON(labels, valueList), response);
                break;
            /**
             * 导出TXT
             */
            case BaseConstants.EXPORT_FORMAT_TXT:
                exportTxt(fileName, labels, valueList, response);
                break;
            default:
                ResponseUtil.writeJson(response, BaseResult.error(BaseResultEnum.FAILED, "不支持的导出格式"));
        }
    }

    /**
     * 解析json
     *
     * @param labels    标题
     * @param valueList 数值
     * @return
     */
    private JSONArray analysisJSON(List<String> labels, List<List<String>> valueList) {
        JSONArray jsonArray = new JSONArray();
        for (int i = 0; i < valueList.size(); i++) {
            HashMap<String, String> map = new LinkedHashMap<>();
            for (int j = 0; j < labels.size(); j++) {
                map.put(labels.get(j), valueList.get(i).get(j));
            }
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(map));
            jsonArray.add(jsonObject);
        }
        return jsonArray;
    }

    /**
     * 导出CSV
     *
     * @param fileName    文件名称
     * @param columnLabel 标题
     * @param columnValue 数据集合
     * @param response    响应 HttpServletResponse
     * @throws IOException
     */
    public void exportCsv(String fileName, List<String> columnLabel, List<List<String>> columnValue,
                          HttpServletResponse response) throws IOException {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        CsvUtils.writeCsv(os, columnLabel, columnValue);
        os.flush();
        os.close();
        ResponseUtil.csv(fileName, os.toByteArray(), response);

    }

    /**
     * 导出JSON
     *
     * @param fileName 名称
     * @param datas    数据集合
     * @param response HttpServletResponse
     * @throws IOException
     */
    public void exportJson(String fileName, JSONArray datas, HttpServletResponse response) throws IOException {
        ResponseUtil.json(fileName, datas.toString().getBytes(StandardCharsets.UTF_8), response);
    }

    /**
     * 导出text
     *
     * @param fileName    文件名称
     * @param columnLabel 标题
     * @param columnValue 数据集合
     * @param response    响应 HttpServletResponse
     * @throws IOException
     */
    public void exportTxt(String fileName, List<String> columnLabel, List<List<String>> columnValue,
                          HttpServletResponse response) throws IOException {
        StringBuilder write = new StringBuilder();
        String doubleTab = "        ";
        String enter = "\r\n";
        for (String lab : columnLabel) {
            write.append(lab).append(doubleTab);
        }
        write.append(enter);
        for (List<String> list : columnValue) {
            for (String val : list) {
                write.append(val).append(doubleTab);
            }
            write.append(enter);
        }
        ResponseUtil.json(fileName, write.toString().getBytes(StandardCharsets.UTF_8), response);

    }

    /**
     * 导出Excel
     *
     * @param fileName    文件名称
     * @param sheetName   sheet名称
     * @param sheetTitle  sheet标题
     * @param headerNames 标题
     * @param values      值集合
     * @param response    响应
     * @param exportType  导出类型
     * @throws Exception 异常
     */
    public void exportExcel(String fileName, String sheetName, String sheetTitle, List<String> headerNames,
                            List<List<String>> values, HttpServletResponse response, String exportType) throws Exception {
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        ResponseUtil.setAttachmentResponseHeader(response, fileName + "." + exportType);
        OutputStream os = response.getOutputStream();
        ExcelService excelService;
        if (BaseConstants.EXPORT_FORMAT_XLS.equals(exportType)) {
            excelService = ExcelFactory.getExcelService(ExcelEnum.XLS);
        } else {
            excelService = ExcelFactory.getExcelService(ExcelEnum.XLSX);
        }
        excelService.writeExcel(os, sheetName, sheetTitle, headerNames, values);
        // os.flush();
        // os.close();

    }

}
